package com.tang.param_check.aspect.handler;

import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author tangyuan2meicloud.com
 * @DATE 2021/12/17 21:44
 * @Desc
 * @Remarks
 */
@Component
public class HandlerManager {

    private Map<Class, ParamCheckHandle> handleMap;

    public HandlerManager(List<ParamCheckHandle> paramHandles) {
        handleMap = new HashMap<>();
        for (ParamCheckHandle paramHandle : paramHandles) {
            handleMap.put(paramHandle.getClass(), paramHandle);
        }
    }

    /**
     * 具体的处理参数的逻辑
     *
     * @param handlerClass
     * @param arg
     */
    public boolean paramCheckHandler(Class handlerClass, Object arg) {
        /**
         * 是否存在处理类的实例
         */
        if (handleMap.containsKey(handlerClass)) {
            ParamCheckHandle paramCheckHandle = handleMap.get(handlerClass);
            if (paramCheckHandle instanceof BeforeThenParamCheckHandle) {
                return toBeforeThenCheck((BeforeThenParamCheckHandle) paramCheckHandle, arg);
            }
            if (paramCheckHandle instanceof ParamCheckThenAfterHandle) {
                return toCheckThenAfter((ParamCheckThenAfterHandle) paramCheckHandle, arg);
            }
            return toDefaultCheck(paramCheckHandle, arg);
        }
        throw new RuntimeException("无此处理类的实例，请检查");
    }

    /**
     * 默认校验
     *
     * @param paramCheckHandle
     * @param arg
     */
    private boolean toDefaultCheck(ParamCheckHandle paramCheckHandle, Object arg) {
        if (arg instanceof Collection) {
            return paramCheckHandle.handleCollection((Collection) arg);
        } else {
            return paramCheckHandle.handle(arg);
        }
    }

    /**
     * 先进行校验再执行后调用方法
     *
     * @param paramCheckThenAfterHandle
     * @param arg
     * @return
     */
    private boolean toCheckThenAfter(ParamCheckThenAfterHandle paramCheckThenAfterHandle, Object arg) {
        if (arg instanceof Collection) {
            boolean flag = paramCheckThenAfterHandle.handleCollection((Collection) arg);
            paramCheckThenAfterHandle.afterCollectionCheck((Collection) arg);
            return flag;
        } else {
            boolean flag = paramCheckThenAfterHandle.handle(arg);
            paramCheckThenAfterHandle.afterDomainCheck(arg);
            return flag;
        }
    }

    /**
     * 先执行调用方法，再进行参数校验逻辑
     *
     * @param beforeThenParamCheckHandle
     * @param arg
     * @return
     */
    private boolean toBeforeThenCheck(BeforeThenParamCheckHandle beforeThenParamCheckHandle, Object arg) {
        if (arg instanceof Collection) {
            beforeThenParamCheckHandle.beforeCollectionCheck((Collection) arg);
            return beforeThenParamCheckHandle.handleCollection((Collection) arg);
        } else {
            beforeThenParamCheckHandle.beforeDomainCheck(arg);
            return beforeThenParamCheckHandle.handle(arg);
        }
    }

    public boolean handle(Class clazz, Object param) {
        if (handleMap.containsKey(clazz)) {
            ParamCheckHandle paramHandle = handleMap.get(clazz);
            return paramHandle.handle(param);
        }
        return true;
    }

    public boolean handleCollection(Class clazz, Collection param) {
        if (handleMap.containsKey(clazz)) {
            ParamCheckHandle paramHandle = handleMap.get(clazz);
            return paramHandle.handleCollection(param);
        }
        return true;
    }
}
